package cn.imatu.framework.flyway.executor;

import cn.hutool.core.util.StrUtil;
import cn.imatu.framework.flyway.FlywayException;
import cn.imatu.framework.flyway.entity.FlywaySql;
import cn.imatu.framework.flyway.mapper.FlywayMapper;
import cn.imatu.framework.flyway.properties.LyFlywayProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @author shenguangyang
 */
@Slf4j
public abstract class FlywayExecutor {
    @Resource(name = "lyFlywayProperties")
    protected LyFlywayProperties properties;
    @Resource
    protected FlywayMapper flywayMapper;
    @Resource
    protected JdbcTemplate jdbcTemplate;

    public abstract void initTable();


    public boolean isIgnore(String sqlStr, FlywaySql sqlObj) {
        return false;
    }

    /**
     * 执行sql
     */
    @Transactional(rollbackFor = Exception.class)
    public void execSql(FlywaySql sqlObj) {
        try {
            log.info("flyway 执行sql: {}", sqlObj.getScript());
            long beginTime = System.currentTimeMillis();
            String[] sqlSplit = sqlObj.getSql().split("\n");

            StringBuilder tempSql = new StringBuilder();
            for (String sql : sqlSplit) {
                if (StrUtil.isEmpty(sql)) {
                    continue;
                }
                if (sql.endsWith(";")) {
                    tempSql.append(sql);
                    String execSql = tempSql.toString();
                    if (this.isIgnore(execSql, sqlObj)) {
                        throw new FlywayException("flyway 执行 {} 异常(不允许执行drop或delete) ", sqlObj.getScript());
                    }
                    this.jdbcTemplate.execute(execSql);
                    tempSql = new StringBuilder();
                    continue;
                }
                tempSql.append(sql);
            }

            sqlObj.setExecutionTime(System.currentTimeMillis() - beginTime);
            sqlObj.setSuccess(1);
            this.flywayMapper.insert(sqlObj);
        } catch (Exception e) {
            log.error("error: ", e);
            throw new FlywayException("flyway 执行 {} 异常: {}", sqlObj.getScript(), e.getMessage());
        }
    }

}
